home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / tf-texmp / mcga.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-10-10  |  42.7 KB  |  1,895 lines

  1. {$A+}
  2. UNIT MCGA;   { Copyright by Stefan Ohrhallinger in 1991,92,93 }
  3.              { aka »The Faker« of AARDVARK }
  4. INTERFACE
  5. CONST
  6.      Up=0;
  7.      Right=1;
  8.      Down=2;
  9.      Left=3;
  10.  
  11. PROCEDURE SetPixel(X,Y:Word; C:Byte);
  12. FUNCTION GetPixel(X,Y:Word):Byte;
  13. PROCEDURE DrawLineH(X1,X2,Y1:Word; C:Byte);
  14. PROCEDURE DrawLineV(X1,Y1,Y2:Word; C:Byte);
  15. PROCEDURE DrawLine(X1,Y1,X2,Y2:Integer; C:Byte);
  16. PROCEDURE SetColor(Nr,R,G,B:Byte);
  17. PROCEDURE GetColor(Nr:Byte; VAR R,G,B:Byte);
  18. FUNCTION PaintChar(Ch,X,Y:Integer; C:Byte):Boolean;
  19. PROCEDURE GrWrite(X,Y:Integer; C:Byte; S:String);
  20. PROCEDURE LoadFont(Nr:Byte; Name:String);
  21. PROCEDURE SetText(Nr:Byte; MultX,DivX,MultY,DivY:Byte);
  22. PROCEDURE DrawPolygon(Count:Integer; VAR P; C:Byte);
  23. PROCEDURE Fill(X,Y:Integer; C:Byte);  { Nur die selbe Farbe ersetzen }
  24. PROCEDURE Flood(X,Y:Integer; C,C2:Byte);  { Anfärben bis zur Randfarbe C2 }
  25. PROCEDURE MCGAOn;
  26. PROCEDURE MCGAOff;
  27. PROCEDURE FillPolygon(Size:Integer; VAR P1; C:Byte);
  28. PROCEDURE Ellipse(MX,MY,A,B:Integer; C:Byte);
  29. PROCEDURE FillEllipse(MX,MY,A,B:Integer; C:Byte);
  30. PROCEDURE Circle(X,Y,R:Integer; C:Byte);
  31. PROCEDURE FillCircle(X,Y,R:Integer; C:Byte);
  32. PROCEDURE RotateArray(VAR P; Count,MX,MY:Integer; Winkel:Real);
  33. PROCEDURE N4eck(N,X,Y,R1,R2:Integer; C:Byte);
  34. PROCEDURE Neck(N,X,Y,A,B:Integer; Drehen:Real);
  35. PROCEDURE DrawRing(X,Y,R1,R2:Integer; C:Byte);
  36. PROCEDURE FillRing(X,Y,R1,R2:Integer; C:Byte);
  37. PROCEDURE SetFrameColor(C:Byte);
  38. PROCEDURE RecTangle(X1,Y1,X2,Y2:Integer; C:Byte);
  39. PROCEDURE GetImage(X1,Y1,X2,Y2:Integer; VAR P);
  40. PROCEDURE PutImage(X1,Y1:Integer; VAR P);
  41. PROCEDURE PutImagePart(X1,Y1,XS2,YS2:Integer; VAR P);
  42. PROCEDURE FillBlock(X1,Y1,X2,Y2:Integer; C:Byte);
  43. PROCEDURE ScrollLeft(X1,Y1,X2,Y2:Word);
  44. PROCEDURE ScrollRight(X1,Y1,X2,Y2:Word);
  45. PROCEDURE ScrollUp(X1,Y1,X2,Y2:Word);
  46. PROCEDURE ScrollDown(X1,Y1,X2,Y2:Word);
  47. PROCEDURE Scroll(Direction:Byte; X1,Y1,X2,Y2:Word);
  48. PROCEDURE SwitchOff;
  49. PROCEDURE SwitchOn;
  50. PROCEDURE LoadPalette(DateiName:String);
  51. PROCEDURE SavePalette(DateiName:String);
  52. PROCEDURE LoadScreen(DateiName:String);
  53. PROCEDURE SaveScreen(DateiName:String);
  54. PROCEDURE BCircle(X,Y,R:Integer; C:Byte);
  55. PROCEDURE BFillCircle(X,Y,R:Integer; C:Byte);
  56. PROCEDURE Split(Row:Integer);
  57. PROCEDURE ScrollText(Nr:Word);
  58. PROCEDURE SetStart(S:Word);
  59. PROCEDURE VerticalRetrace;
  60. PROCEDURE SetOffset(B:Byte);
  61. PROCEDURE LoadSprite(DateiName:String; VAR P);
  62. PROCEDURE SaveSprite(DateiName:String; VAR P);
  63. FUNCTION SpriteXSize(Sprite:Pointer):Word;
  64. FUNCTION SpriteYSize(Sprite:Pointer):Word;
  65. FUNCTION SpriteSize(Sprite:Pointer):Word;
  66. PROCEDURE FillScreen(C:Byte);
  67. PROCEDURE SetChain4;
  68. PROCEDURE ClearChain4;
  69. PROCEDURE CharHeight(B:Byte);
  70. PROCEDURE Wait4Line;
  71. PROCEDURE CLI;
  72. PROCEDURE STI;
  73. PROCEDURE PutImage4(X1,Y1:Integer; VAR P);
  74. PROCEDURE SetWriteMap(Map:Byte);
  75. PROCEDURE SetWriteMode(M:Byte);
  76. PROCEDURE Unchain;
  77. PROCEDURE Rechain;
  78. PROCEDURE ClearScreen;
  79. PROCEDURE SetModeNr(Nr:Word);
  80. PROCEDURE SetModeReg(Reg:String);
  81. PROCEDURE Init13X;
  82. PROCEDURE SetReadMap(Map:Byte);
  83. PROCEDURE SetLineRepeat(Nr:Byte);
  84. PROCEDURE SetDoubleLines(Ok:Boolean);
  85. PROCEDURE SetHorizOfs(Count:Byte);
  86. PROCEDURE DrawLineH4(X1,X2,Y:Integer; C:Byte);
  87. PROCEDURE DrawLineV4(X,Y1,Y2:Integer; C:Byte);
  88.  
  89. IMPLEMENTATION
  90. CONST
  91.      MaxFont=4;
  92.      FontName:ARRAY[1..MaxFont] OF String[4]=('TRIP','LITT','SANS','GOTH');
  93.      VekMax=100;
  94.      X_zu_Y=0.69;
  95. TYPE
  96.     FontType=RECORD
  97.                    FBuf:ARRAY[0..16000] OF Byte;
  98.                    WPtr:^Word;
  99.                    DataOffs,MinChar,TBStart,TblSize,WidthTbl,VecStart,CUp,CDown:Integer;
  100.                    GLine,Index,CharWidth:Integer;
  101.              END;
  102. VAR
  103.    Font:ARRAY[1..4] OF ^FontType;
  104.    FontNr,MX,DX,MY,DY:Byte;
  105.    CurrMode,OldMode:Byte;
  106.  
  107. PROCEDURE SetPixel(X,Y:Word; C:Byte);
  108. BEGIN
  109.      ASM
  110.         mov ax,$a000
  111.         mov es,ax
  112.         mov bx,x
  113.         mov dx,y
  114.         xchg dh,dl
  115.         mov al,c
  116.         mov di,dx
  117.         shr di,1
  118.         shr di,1
  119.         add di,dx
  120.         add di,bx
  121.         stosb
  122.      END;
  123. END;
  124.  
  125. FUNCTION GetPixel(X,Y:Word):Byte;
  126. BEGIN
  127.      ASM
  128.         mov ax,$a000
  129.         mov es,ax
  130.         mov bx,x
  131.         mov dx,y
  132.         mov di,dx
  133.         shl di,1
  134.         shl di,1
  135.         add di,dx
  136.         mov cl,6
  137.         shl di,cl
  138.         add di,bx
  139.         mov al,es:[di]
  140.         mov [bp-1],al
  141.      END;
  142. END;
  143.  
  144. PROCEDURE DrawLineH(X1,X2,Y1:Word; C:Byte);
  145. BEGIN
  146.      ASM
  147.         mov ax,$a000
  148.         mov es,ax
  149.         mov ax,y1
  150.         mov di,ax
  151.         shl di,1
  152.         shl di,1
  153.         add di,ax
  154.         mov cl,6
  155.         shl di,cl
  156.         mov bx,x1
  157.         mov dx,x2
  158.         cmp bx,dx
  159.         jl @1
  160.         xchg bx,dx
  161. @1:     inc dx
  162.         add di,bx
  163.         mov cx,dx
  164.         sub cx,bx
  165.         shr cx,1
  166.         mov al,c
  167.         mov ah,al
  168.         ror bx,1
  169.         jnb @2
  170.         stosb
  171.         ror dx,1
  172.         jnb @3
  173.         dec cx
  174. @3:     rol dx,1
  175. @2:     rep
  176.         stosw
  177.         ror dx,1
  178.         jnb @4
  179.         stosb
  180. @4:  END;
  181. END;
  182.  
  183. PROCEDURE DrawLineV(X1,Y1,Y2:Word; C:Byte);
  184. BEGIN
  185.      ASM
  186.         mov ax,x1
  187.         mov bx,y1
  188.         mov dx,y2
  189.         cmp bx,dx
  190.         jl @1
  191.         xchg bx,dx
  192. @1:     mov di,bx
  193.         shl di,1
  194.         shl di,1
  195.         add di,bx
  196.         mov cl,6
  197.         shl di,cl
  198.         add di,ax
  199.         mov cx,$a000
  200.         mov es,cx
  201.         mov cx,dx
  202.         sub cx,bx
  203.         inc cx
  204.         mov al,c
  205.         mov bx,$13f
  206. @2:     stosb
  207.         add di,bx
  208.         loop @2
  209.      END;
  210. END;
  211.  
  212. PROCEDURE DrawLine(X1,Y1,X2,Y2:Integer; C:Byte);
  213. BEGIN
  214.      ASM
  215.         mov al,c
  216.         xor ah,ah
  217.         mov si,ax
  218.         mov ax,x1
  219.         cmp ax,319
  220.         ja @Ende
  221.         mov bx,x2
  222.         cmp bx,319
  223.         ja @Ende
  224.         mov cx,y1
  225.         cmp cx,199
  226.         ja @Ende
  227.         mov dx,y2
  228.         cmp dx,199
  229.         ja @Ende
  230.         cmp ax,bx
  231.         jnz @weiter
  232.         cmp cx,dx
  233.         jnz @vertical
  234.         push ax
  235.         push cx
  236.         push si
  237.         call setpixel
  238.         jmp @ende
  239. @weiter:cmp cx,dx
  240.         jnz @weiter2
  241.         push ax
  242.         push bx
  243.         push cx
  244.         push si
  245.         call drawlineh
  246.         jmp @ende
  247. @vertical:push ax
  248.         push cx
  249.         push dx
  250.         push si
  251.         call drawlinev
  252.         jmp @ende
  253. @weiter2:cmp cx,dx
  254.         jbe @1
  255.         xchg cx,dx
  256.         xchg ax,bx
  257. @1:     mov di,cx
  258.         shl di,1
  259.         shl di,1
  260.         add di,cx
  261.         push si
  262.         mov si,bx
  263.         mov bx,dx
  264.         sub bx,cx
  265.         mov cl,06
  266.         shl di,cl
  267.         add di,ax
  268.         mov dx,si
  269.         pop si
  270.         sub dx,ax
  271.         mov ax,$a000
  272.         mov es,ax
  273.         mov ax,si
  274.         push bp
  275.         or dx,0
  276.         jge @jmp1
  277.         neg dx
  278.         cmp dx,bx
  279.         jbe @jmp3
  280.         mov cx,dx
  281.         inc cx
  282.         mov si,dx
  283.         shr si,1
  284.         std
  285.         mov bp,320
  286. @1c:    stosb
  287. @1b:    or si,si
  288.         jge @1a
  289.         add di,bp
  290.         add si,dx
  291.         jmp @1b
  292. @1a:    sub si,bx
  293.         loop @1c
  294.         jmp @Ende2
  295. @jmp3:  mov cx,bx
  296.         inc cx
  297.         mov si,bx
  298.         neg si
  299.         sar si,1
  300.         cld
  301.         mov bp,319
  302. @2c:    stosb
  303. @2b:    or si,si
  304.         jl @2a
  305.         sub si,bx
  306.         dec di
  307.         jmp @2b
  308. @2a:    add di,bp
  309.         add si,dx
  310.         loop @2c
  311.         jmp @Ende2
  312. @jmp1:  cmp dx,bx
  313.         jbe @jmp4
  314.         mov cx,dx
  315.         inc cx
  316.         mov si,dx
  317.         shr si,1
  318.         cld
  319.         mov bp,320
  320. @3c:    stosb
  321. @3b:    or si,si
  322.         jge @3a
  323.         add di,bp
  324.         add si,dx
  325.         jmp @3b
  326. @3a:    sub si,bx
  327.         loop @3c
  328.         jmp @Ende2
  329. @jmp4:  mov cx,bx
  330.         inc cx
  331.         mov si,bx
  332.         neg si
  333.         sar si,1
  334.         std
  335.         mov bp,321
  336. @4c:    stosb
  337. @4b:    or si,si
  338.         jl @4a
  339.         sub si,bx
  340.         inc di
  341.         jmp @4b
  342. @4a:    add di,bp
  343.         add si,dx
  344.         loop @4c
  345. @Ende2: pop bp
  346.         cld
  347. @Ende:END;
  348. END;
  349.  
  350. PROCEDURE SetColor(Nr,R,G,B:Byte);
  351. BEGIN
  352.      Port[$3C8]:=Nr;
  353.      Port[$3C9]:=R;
  354.      Port[$3C9]:=G;
  355.      Port[$3C9]:=B;
  356. END;
  357.  
  358. PROCEDURE GetColor(Nr:Byte; VAR R,G,B:Byte);
  359. BEGIN
  360.      Port[$3C7]:=Nr;
  361.      R:=Port[$3C9];
  362.      G:=Port[$3C9];
  363.      B:=Port[$3C9];
  364. END;
  365.  
  366. FUNCTION PaintChar(Ch,X,Y:Integer; C:Byte):Boolean;
  367. VAR
  368.    XVec,YVec,Func,GraphX,GraphY:Integer;
  369. BEGIN
  370.      PaintChar:=FALSE;
  371.      WITH Font[FontNr]^ DO
  372.      BEGIN
  373.           IF (Ch<MinChar) OR (Ch>MinChar+TblSize-1) THEN
  374.              Exit;
  375.           Index:=VecStart+FBuf[TBStart+(Ch-MinChar)*2]+FBuf[TBStart+(Ch-MinChar)*2+1]*256;
  376.           REPEAT
  377.                 XVec:=ShortInt(FBuf[Index]);
  378.                 YVec:=ShortInt(FBuf[Index+1]);
  379.                 Inc(Index,2);
  380.                 Func:=(XVec AND $80) SHR 6+(YVec AND $80) SHR 7;
  381.                 XVec:=XVec AND $7F;
  382.                 YVec:=YVec AND $7F;
  383.                 IF XVec>=$40 THEN
  384.                    XVec:=-128+XVec;
  385.                 IF YVec>=$40 THEN
  386.                    YVec:=-128+YVec;
  387.                 IF MX<>1 THEN
  388.                    XVec:=XVec*MX;
  389.                 IF DX<>1 THEN
  390.                    XVec:=XVec DIV DX;
  391.                 IF MY<>1 THEN
  392.                    YVec:=YVec*MY;
  393.                 IF DY<>1 THEN
  394.                    YVec:=YVec DIV DY;
  395.                 CASE Func OF
  396.                      2:BEGIN
  397.                             GraphX:=X+XVec;
  398.                             GraphY:=CUp+Y-YVec;
  399.                        END;
  400.                      3:BEGIN
  401.                             DrawLine(X+XVec,CUp+Y-YVec,GraphX,GraphY,C);
  402.                             GraphX:=X+XVec;
  403.                             GraphY:=CUp+Y-YVec;
  404.                        END;
  405.                 END;
  406.           UNTIL Func=0;
  407.      END;
  408.      PaintChar:=TRUE;
  409. END;
  410.  
  411. PROCEDURE GrWrite(X,Y:Integer; C:Byte; S:String);
  412. VAR
  413.    I:Byte;
  414. BEGIN
  415.      WITH Font[FontNr]^ DO
  416.      BEGIN
  417.           FOR I:=1 TO Ord(S[0]) DO
  418.           BEGIN
  419.                IF X+FBuf[WidthTbl+Ord(S[I])-MinChar]*MX DIV DX>319 THEN
  420.                BEGIN
  421.                     X:=0;
  422.                     IF Y+(CUp-CDown)*MY DIV DY>319 THEN
  423.                        Exit;
  424.                     Inc(Y,(CUp-CDown)*MY DIV DY);
  425.                END;
  426.                IF PaintChar(Ord(S[I]),X,Y,C) THEN
  427.                   Inc(X,(FBuf[WidthTbl+Ord(S[I])-MinChar])*MX DIV DX);
  428.           END;
  429.      END;
  430. END;
  431.  
  432. PROCEDURE LoadFont(Nr:Byte; Name:String);
  433. VAR
  434.    X:Integer;
  435.    ChrFile:File;
  436. BEGIN
  437.      New(Font[Nr]);
  438.      WITH Font[Nr]^ DO
  439.      BEGIN
  440.           Assign(ChrFile,Name+'.CHR');
  441.           Reset(ChrFile,1);
  442.           BlockRead(ChrFile,FBuf,FileSize(ChrFile));
  443.           Close(ChrFile);
  444.           X:=0;
  445.           WHILE (X<$80) AND (FBuf[X]<>$1A) DO
  446.                 Inc(X);
  447.           Inc(X);
  448.           DataOffs:=FBuf[X]+FBuf[X+1] SHL 8;
  449.           TblSize:=FBuf[DataOffs+1];
  450.           MinChar:=FBuf[DataOffs+4];
  451.           CUp:=FBuf[DataOffs+8];
  452.           CDown:=ShortInt(FBuf[DataOffs+$0A]);
  453.           TBStart:=DataOffs+$10;
  454.           WidthTbl:=TBStart+TblSize SHL 1;
  455.           WPtr:=@FBuf[DataOffs+5];
  456.           VecStart:=WPtr^+DataOffs;
  457.      END;
  458. END;
  459.  
  460. PROCEDURE SetText(Nr:Byte; MultX,DivX,MultY,DivY:Byte);
  461. BEGIN
  462.      IF (Nr<1) OR (Nr>MaxFont) THEN
  463.         Exit;
  464.      IF Font[Nr]=NIL THEN
  465.         LoadFont(Nr,FontName[Nr]);
  466.      FontNr:=Nr;
  467.      MX:=MultX;
  468.      DX:=DivX;
  469.      MY:=MultY;
  470.      DY:=DivY;
  471. END;
  472.  
  473. PROCEDURE DrawPolygon(Count:Integer; VAR P; C:Byte);
  474. TYPE
  475.     PunkteArray=ARRAY[1..16383,1..2] OF Integer;
  476. VAR
  477.    A:PunkteArray ABSOLUTE P;
  478.    I:Integer;
  479. BEGIN
  480.      DrawLine(A[Count,1],A[Count,2],A[1,1],A[1,2],C);
  481.      FOR I:=2 TO Count DO
  482.          DrawLine(A[I-1,1],A[I-1,2],A[I,1],A[I,2],C);
  483. END;
  484.  
  485. PROCEDURE Fill(X,Y:Integer; C:Byte);  { Nur die selbe Farbe ersetzen }
  486. VAR
  487.    C2:Byte;
  488.  
  489.    PROCEDURE Suchen(L,R,Y:Integer; UpDown:Byte);
  490.    VAR
  491.       X,X2:Integer;
  492.    BEGIN
  493.         IF GetPixel(L,Y)=C2 THEN
  494.            WHILE (L>0) AND (GetPixel(L-1,Y)=C2) DO
  495.                  Dec(L);
  496.         X:=L;
  497.         IF GetPixel(R,Y)=C2 THEN
  498.            WHILE (R<319) AND (GetPixel(R+1,Y)=C2) DO
  499.                  Inc(R);
  500.         WHILE X<=R DO
  501.         BEGIN
  502.              X2:=X;
  503.              IF GetPixel(X,Y)=C2 THEN
  504.              BEGIN
  505.                   WHILE (GetPixel(X+1,Y)=C2) AND (X<319) DO
  506.                         Inc(X);
  507.                   DrawLineH(X2,X,Y,C);
  508.                   IF UpDown=2 THEN
  509.                   BEGIN
  510.                        IF Y>0 THEN
  511.                           Suchen(X2,X,Y-1,2);
  512.                        IF Y<199 THEN
  513.                           IF (L>X2) AND (R<X) THEN
  514.                           BEGIN
  515.                                Suchen(X2,L-1,Y+1,1);
  516.                                Suchen(R+1,X,Y+1,1);
  517.                           END
  518.                           ELSE
  519.                           IF (L<=X2) AND (R<X) THEN
  520.                              Suchen(R+1,X,Y+1,1)
  521.                           ELSE
  522.                           IF (L>X2) AND (R>=X) THEN
  523.                              Suchen(X2,L-1,Y+1,1);
  524.                   END;
  525.                   IF UpDown=1 THEN
  526.                   BEGIN
  527.                        IF Y<199 THEN
  528.                           Suchen(X2,X,Y+1,1);
  529.                        IF Y>0 THEN
  530.                           IF (L>X2) AND (R<X) THEN
  531.                           BEGIN
  532.                                Suchen(X2,L-1,Y-1,2);
  533.                                Suchen(R+1,X,Y-1,2);
  534.                           END
  535.                           ELSE
  536.                           IF (L<=X2) AND (R<X) THEN
  537.                              Suchen(R+1,X,Y-1,2)
  538.                           ELSE
  539.                           IF (L>X2) AND (R>=X) THEN
  540.                              Suchen(X2,L-1,Y-1,2);
  541.                   END;
  542.              END;
  543.              Inc(X);
  544.         END;
  545.    END;
  546.  
  547. BEGIN
  548.      C2:=GetPixel(X,Y);
  549.      IF Y<>0 THEN
  550.         Dec(Y);
  551.      Suchen(X,X,Y,2);
  552.      Suchen(X,X,Y+1,1);
  553. END;
  554.  
  555. PROCEDURE Flood(X,Y:Integer; C,C2:Byte);  { Anfärben bis zur Randfarbe C2 }
  556.  
  557.    PROCEDURE Suchen(L,R,Y:Integer; UpDown:Byte);
  558.    VAR
  559.       X,X2:Integer;
  560.    BEGIN
  561.         IF GetPixel(L,Y)<>C2 THEN
  562.            WHILE (L>0) AND (GetPixel(L-1,Y)<>C2) DO
  563.                  Dec(L);
  564.         X:=L;
  565.         IF GetPixel(R,Y)<>C2 THEN
  566.            WHILE (R<319) AND (GetPixel(R+1,Y)<>C2) DO
  567.                  Inc(R);
  568.         WHILE X<=R DO
  569.         BEGIN
  570.              X2:=X;
  571.              IF GetPixel(X,Y)<>C2 THEN
  572.              BEGIN
  573.                   WHILE (GetPixel(X+1,Y)<>C2) AND (X<319) DO
  574.                         Inc(X);
  575.                   DrawLineH(X2,X,Y,C);
  576.                   IF UpDown=2 THEN
  577.                   BEGIN
  578.                        IF Y>0 THEN
  579.                           Suchen(X2,X,Y-1,2);
  580.                        IF Y<199 THEN
  581.                           IF (L>X2) AND (R<X) THEN
  582.                           BEGIN
  583.                                Suchen(X2,L-1,Y+1,1);
  584.                                Suchen(R+1,X,Y+1,1);
  585.                           END
  586.                           ELSE
  587.                           IF (L<=X2) AND (R<X) THEN
  588.                              Suchen(R+1,X,Y+1,1)
  589.                           ELSE
  590.                           IF (L>X2) AND (R>=X) THEN
  591.                              Suchen(X2,L-1,Y+1,1);
  592.                   END;
  593.                   IF UpDown=1 THEN
  594.                   BEGIN
  595.                        IF Y<199 THEN
  596.                           Suchen(X2,X,Y+1,1);
  597.                        IF Y>0 THEN
  598.                           IF (L>X2) AND (R<X) THEN
  599.                           BEGIN
  600.                                Suchen(X2,L-1,Y-1,2);
  601.                                Suchen(R+1,X,Y-1,2);
  602.                           END
  603.                           ELSE
  604.                           IF (L<=X2) AND (R<X) THEN
  605.                              Suchen(R+1,X,Y-1,2)
  606.                           ELSE
  607.                           IF (L>X2) AND (R>=X) THEN
  608.                              Suchen(X2,L-1,Y-1,2);
  609.                   END;
  610.              END;
  611.              Inc(X);
  612.         END;
  613.    END;
  614.  
  615. BEGIN
  616.      IF Y<>0 THEN
  617.         Dec(Y);
  618.      Suchen(X,X,Y,2);
  619.      Suchen(X,X,Y+1,1);
  620. END;
  621.  
  622. PROCEDURE MCGAOn;
  623. BEGIN
  624.      ASM
  625.         mov ah,$f
  626.         int $10
  627.         mov [offset oldmode],al
  628.      END;
  629.      ASM
  630.         mov ax,$13
  631.         int $10
  632.      END;
  633. END;
  634.  
  635. PROCEDURE MCGAOff;
  636. BEGIN
  637.      ASM
  638.         mov al,[offset oldmode]
  639.         xor ah,ah
  640.         int $10
  641.      END;
  642. END;
  643.  
  644. PROCEDURE FillPolygon(Size:Integer; VAR P1; C:Byte);
  645. TYPE
  646.     Vektor=RECORD
  647.                  X,Y,XMax,DX,DY,DZ,Z,Spalte:Integer;
  648.            END;
  649.     VekPoly=ARRAY[1..VekMax,1..2,1..2] OF Integer;
  650. VAR
  651.    P:ARRAY[1..VekMax,1..2] OF Integer ABSOLUTE P1;
  652.    Sp:VekPoly;
  653.    NF:Boolean;
  654.    V:ARRAY[1..VekMax] OF Vektor;
  655.    S:ARRAY[1..2*VekMax] OF Integer;
  656.    I,J,K,N,SX,YRMin,YRMax,YR,XMin,YMin,YMax,I2:Integer;
  657. BEGIN
  658.      IF Size>VekMax THEN
  659.         Exit;
  660.      K:=1;
  661.      FOR I:=1 TO Size DO
  662.      BEGIN
  663.           Sp[K,1,1]:=P[I,1];
  664.           Sp[K,1,2]:=P[I,2];
  665.           IF I=Size THEN
  666.           BEGIN
  667.                Sp[K,2,1]:=P[1,1];
  668.                Sp[K,2,2]:=P[1,2];
  669.           END
  670.           ELSE
  671.           BEGIN
  672.                Sp[K,2,1]:=P[I+1,1];
  673.                Sp[K,2,2]:=P[I+1,2];
  674.           END;
  675.           IF Sp[K,2,2]-Sp[K,1,2]<0 THEN
  676.           BEGIN
  677.                J:=Sp[K,2,1];
  678.                Sp[K,2,1]:=Sp[K,1,1];
  679.                Sp[K,1,1]:=J;
  680.                J:=Sp[K,2,2];
  681.                Sp[K,2,2]:=Sp[K,1,2];
  682.                Sp[K,1,2]:=J;
  683.           END;
  684.           Inc(K);
  685.      END;
  686.      YRMin:=199;
  687.      YRMax:=0;
  688.      FOR K:=1 TO Size DO
  689.          FOR I:=1 TO 2 DO
  690.          BEGIN
  691.               IF Sp[K,I,2]>YRMax THEN
  692.                  YRMax:=Sp[K,I,2];
  693.               IF Sp[K,I,2]<YRMin THEN
  694.                  YRMin:=Sp[K,I,2];
  695.          END;
  696.      IF YRMin<0 THEN
  697.         YRMin:=0;
  698.      IF YRMax>199 THEN
  699.         YRMax:=199;
  700.      FOR K:=1 TO Size DO
  701.          WITH V[K] DO
  702.          BEGIN
  703.               XMin:=Sp[K,1,1];
  704.               YMin:=Sp[K,1,2];
  705.               XMax:=Sp[K,2,1];
  706.               YMax:=Sp[K,2,2];
  707.               DX:=Abs(XMin-XMax);
  708.               DY:=Abs(YMin-YMax);
  709.               X:=XMin;
  710.               Y:=YMin;
  711.               IF XMin<XMax THEN
  712.                  Z:=1
  713.               ELSE Z:=-1;
  714.               IF DX>DY THEN
  715.                  I2:=DX
  716.               ELSE I2:=DY;
  717.               DZ:=I2 DIV 2;
  718.               Spalte:=XMin;
  719.          END;
  720.      FOR YR:=YRMin TO YRMax DO
  721.      BEGIN
  722.           N:=0;
  723.           FOR K:=1 TO Size DO
  724.               IF ((Sp[K,1,2]<=YR) AND (YR<SP[K,2,2])) OR ((YR=YRMax) AND (YRMax=Sp[K,2,2]) AND (YRMax<>Sp[K,1,2])) THEN
  725.               BEGIN
  726.                    WITH V[K] DO
  727.                    BEGIN
  728.                         Inc(N);
  729.                         S[N]:=X;
  730.                         SX:=X;
  731.                         REPEAT
  732.                               IF DZ<DX THEN
  733.                               BEGIN
  734.                                    DZ:=DZ+DY;
  735.                                    X:=X+Z;
  736.                               END;
  737.                               IF DZ>=DX THEN
  738.                               BEGIN
  739.                                    DZ:=DZ-DX;
  740.                                    Inc(Y);
  741.                               END;
  742.                               IF Y=YR THEN
  743.                                  SX:=X;
  744.                               Inc(Spalte,Z);
  745.                         UNTIL (Y>YR) OR (Spalte=XMax);
  746.                         Inc(N);
  747.                         S[N]:=SX;
  748.                    END;
  749.               END;
  750.           FOR I:=2 TO N DO
  751.               FOR K:=N DOWNTO I DO
  752.                   IF S[K-1]>S[K] THEN
  753.                   BEGIN
  754.                        J:=S[K-1];
  755.                        S[K-1]:=S[K];
  756.                        S[K]:=J;
  757.                   END;
  758.           K:=1;
  759.           WHILE K<=N DO
  760.           BEGIN
  761.                IF S[K]<0 THEN
  762.                   S[K]:=0;
  763.                IF S[K+3]>319 THEN
  764.                   S[K+3]:=319;
  765.                DrawLineH(S[K],S[K+3],YR,C);
  766.                K:=K+4;
  767.           END;
  768.      END;
  769. END;
  770.  
  771. PROCEDURE Ellipse(MX,MY,A,B:Integer; C:Byte);
  772. VAR
  773.    X,Y,X2,J:Integer;
  774. BEGIN
  775.      Dec(B);
  776.      X2:=A;
  777.      FOR Y:=0 TO B DO
  778.      BEGIN
  779.           X:=Trunc(A/B*Sqrt(Sqr(B)-Sqr(Y-0.5)));
  780.           FOR J:=X TO X2 DO
  781.           BEGIN
  782.                SetPixel(MX+J,MY+Y,C);
  783.                SetPixel(MX-J,MY+Y,C);
  784.                SetPixel(MX+J,MY-Y,C);
  785.                SetPixel(MX-J,MY-Y,C);
  786.           END;
  787.           X2:=X;
  788.      END;
  789.      Inc(B);
  790.      FOR J:=0 TO X DO
  791.      BEGIN
  792.           SetPixel(MX+J,MY+B,C);
  793.           SetPixel(MX-J,MY+B,C);
  794.           SetPixel(MX+J,MY-B,C);
  795.           SetPixel(MX-J,MY-B,C);
  796.      END;
  797. END;
  798.  
  799. PROCEDURE FillEllipse(MX,MY,A,B:Integer; C:Byte);
  800. VAR
  801.    X,Y,X2,J:Integer;
  802. BEGIN
  803.      Dec(B);
  804.      X2:=A;
  805.      DrawLineH(MX-A,MX+A,MY,C);
  806.      FOR Y:=1 TO B DO
  807.      BEGIN
  808.           X:=Trunc(A/B*Sqrt((Sqr(LongInt(B)))-Sqr(Y-0.5)));
  809.           DrawLineH(MX-X,MX+X,MY+Y,C);
  810.           DrawLineH(MX-X,MX+X,MY-Y,C);
  811.           X2:=X;
  812.      END;
  813. END;
  814.  
  815. PROCEDURE Circle(X,Y,R:Integer; C:Byte);
  816. BEGIN
  817.      Ellipse(X,Y,R,Trunc(R*X_zu_Y),C);
  818. END;
  819.  
  820. PROCEDURE FillCircle(X,Y,R:Integer; C:Byte);
  821. BEGIN
  822.      FillEllipse(X,Y,R,Round(R*X_zu_Y),C);
  823. END;
  824.  
  825. PROCEDURE RotateArray(VAR P; Count,MX,MY:Integer; Winkel:Real);
  826. TYPE
  827.     PunkteArray=ARRAY[1..16383,1..2] OF Integer;
  828. VAR
  829.    A:PunkteArray ABSOLUTE P;
  830.    I,X,Y:Integer;
  831.    CosWi,SinWi:Real;
  832. BEGIN
  833.      Winkel:=-Pi*Winkel/180;
  834.      CosWi:=Cos(Winkel);
  835.      SinWi:=Sin(Winkel);
  836.      FOR I:=1 TO Count DO
  837.      BEGIN
  838.           X:=A[I,1]-MX;
  839.           Y:=A[I,2]-MY;
  840.           A[I,1]:=Round(X*CosWi+Y*SinWi)+MX;
  841.           A[I,2]:=Round(-X*SinWi+Y*CosWi)+MY;
  842.      END;
  843. END;
  844.  
  845. PROCEDURE N4eck(N,X,Y,R1,R2:Integer; C:Byte);
  846. VAR
  847.    D:ARRAY[0..100] OF Word;
  848.    I,X1,Y1,X2,Y2:Integer;
  849.    Pi180:Real;
  850. BEGIN
  851.      Pi180:=Pi/180;
  852.      FOR I:=0 TO N DO
  853.          D[I]:=Round(Sin(Pi180*I/N*90)*10000);
  854.      X1:=Round(D[0]*R1/10000);
  855.      Y1:=Round(D[N]*R2/10000);
  856.      FOR I:=1 TO N DO
  857.      BEGIN
  858.           X2:=Round(D[I]*R1/10000);
  859.           Y2:=Round(D[N-I]*R2/10000);
  860.           DrawLine(X-X1,Y+Y1,X-X2,Y+Y2,C);
  861.           DrawLine(X+X1,Y+Y1,X+X2,Y+Y2,C);
  862.           DrawLine(X+X1,Y-Y1,X+X2,Y-Y2,C);
  863.           DrawLine(X-X1,Y-Y1,X-X2,Y-Y2,C);
  864.           X1:=X2;
  865.           Y1:=Y2;
  866.      END;
  867. END;
  868.  
  869. PROCEDURE Neck(N,X,Y,A,B:Integer; Drehen:Real);
  870. VAR
  871.    I:Integer;
  872.    Winkel,Wi:Real;
  873.    P:ARRAY[1..100,1..2] OF Integer;
  874. BEGIN
  875.      Winkel:=2*Pi/N;
  876.      Wi:=Winkel;
  877.      FOR I:=1 TO N DO
  878.      BEGIN
  879.           P[I,1]:=Round(A*Cos(Wi))+X;
  880.           P[I,2]:=Round(B*Sin(Wi))+Y;
  881.           Wi:=Wi+Winkel;
  882.      END;
  883.      IF Drehen<>0 THEN
  884.         RotateArray(P,N,X,Y,Drehen);
  885.      DrawPolygon(N,P,255);
  886. END;
  887.  
  888. PROCEDURE DrawRing(X,Y,R1,R2:Integer; C:Byte);
  889. TYPE
  890.     Arr52=ARRAY[1..52,1..2] OF Integer;
  891. CONST
  892.      D:ARRAY[1..14] OF Integer=(0,1205,2393,3546,4647,5681,6631,7485,8230,8855,9350,9709,9927,10000);
  893.      A:Arr52=(
  894.      (0,10000),(1205,9927),(2393,9709),(3546,9350),(4647,8855),(5681,8230),(6631,7485),
  895.      (7485,6631),(8230,5681),(8855,4647),(9350,3546),(9709,2393),(9927,1205),
  896.      (10000,0),(9927,-1205),(9709,-2393),(9350,-3546),(8855,-4647),(8230,-5681),(7485,-6631),
  897.      (6631,-7485),(5681,-8230),(4647,-8855),(3546,-9350),(2393,-9709),(1205,-9927),
  898.      (0,-10000),(-1205,-9927),(-2393,-9709),(-3546,-9350),(-4647,-8855),(-5681,-8230),(-6631,-7485),
  899.      (-7485,-6631),(-8230,-5681),(-8855,-4647),(-9350,-3546),(-9709,-2393),(-9927,-1205),
  900.      (-10000,0),(-9927,1205),(-9709,2393),(-9350,3546),(-8855,4647),(-8230,5681),(-7485,6631),
  901.      (-6631,7485),(-5681,8230),(-4647,8855),(-3546,9350),(-2393,9709),(-1205,9927));
  902. VAR
  903.    I,X1,Y1,X2,Y2:Integer;
  904.    A2:Arr52;
  905. BEGIN
  906.      A2:=A;
  907.      FOR I:=1 TO 52 DO
  908.      BEGIN
  909.           A2[I,1]:=X+Round(A2[I,1]/10000*R1);
  910.           A2[I,2]:=Y+Round(A2[I,2]/10000*R2);
  911.      END;
  912.      DrawPolygon(52,A2,C);
  913. END;
  914.  
  915. PROCEDURE FillRing(X,Y,R1,R2:Integer; C:Byte);
  916. TYPE
  917.     Arr52=ARRAY[1..52,1..2] OF Integer;
  918. CONST
  919.      D:ARRAY[1..14] OF Integer=(0,1205,2393,3546,4647,5681,6631,7485,8230,8855,9350,9709,9927,10000);
  920.      A:Arr52=(
  921.      (0,10000),(1205,9927),(2393,9709),(3546,9350),(4647,8855),(5681,8230),(6631,7485),
  922.      (7485,6631),(8230,5681),(8855,4647),(9350,3546),(9709,2393),(9927,1205),
  923.      (10000,0),(9927,-1205),(9709,-2393),(9350,-3546),(8855,-4647),(8230,-5681),(7485,-6631),
  924.      (6631,-7485),(5681,-8230),(4647,-8855),(3546,-9350),(2393,-9709),(1205,-9927),
  925.      (0,-10000),(-1205,-9927),(-2393,-9709),(-3546,-9350),(-4647,-8855),(-5681,-8230),(-6631,-7485),
  926.      (-7485,-6631),(-8230,-5681),(-8855,-4647),(-9350,-3546),(-9709,-2393),(-9927,-1205),
  927.      (-10000,0),(-9927,1205),(-9709,2393),(-9350,3546),(-8855,4647),(-8230,5681),(-7485,6631),
  928.      (-6631,7485),(-5681,8230),(-4647,8855),(-3546,9350),(-2393,9709),(-1205,9927));
  929. VAR
  930.    I,X1,Y1,X2,Y2:Integer;
  931.    A2:Arr52;
  932. BEGIN
  933.      A2:=A;
  934.      FOR I:=1 TO 52 DO
  935.      BEGIN
  936.           A2[I,1]:=X+Round(A2[I,1]/10000*R1);
  937.           A2[I,2]:=Y+Round(A2[I,2]/10000*R2);
  938.      END;
  939.      FillPolygon(52,A2,C);
  940. END;
  941.  
  942. PROCEDURE SetFrameColor(C:Byte);
  943. BEGIN
  944.      ASM
  945.         mov ax,$1001
  946.         mov bh,[bp+offset c]
  947.         int $10
  948.      END;
  949. END;
  950.  
  951. PROCEDURE RecTangle(X1,Y1,X2,Y2:Integer; C:Byte);
  952. BEGIN
  953.      DrawLineH(X1,X2,Y1,C);
  954.      DrawLineH(X1,X2,Y2,C);
  955.      DrawLineV(X1,Y1,Y2,C);
  956.      DrawLineV(X2,Y1,Y2,C);
  957. END;
  958.  
  959. PROCEDURE GetImage(X1,Y1,X2,Y2:Integer; VAR P);
  960. VAR
  961.    Data:ARRAY[0..64003] OF Byte ABSOLUTE P;
  962.    I,XS,YS:Word;
  963.    P2:Pointer ABSOLUTE P;
  964. BEGIN
  965.      XS:=X2-X1;
  966.      YS:=Y2-Y1;
  967.      Data[0]:=Lo(XS);
  968.      Data[1]:=Hi(XS);
  969.      Data[2]:=Lo(YS);
  970.      Data[3]:=Hi(YS);
  971.      FOR I:=0 TO YS DO
  972.          Move(Ptr($A000,(Y1+I)*320+X1)^,Data[(XS+1)*I+4],XS+1);
  973. END;
  974. {
  975. PROCEDURE PutImage(X1,Y1:Integer; VAR P);
  976. VAR
  977.    Data:ARRAY[0..64003] OF Byte ABSOLUTE P;
  978.    I,XS,YS:Word;
  979. BEGIN
  980.      XS:=Data[0]+Data[1] SHL 8;
  981.      YS:=Data[2]+Data[3] SHL 8;
  982.      FOR I:=0 TO YS DO
  983.          Move(Data[(XS+1)*I+4],Ptr($A000,(Y1+I)*320+X1)^,XS+1);
  984. END;
  985. }
  986.  
  987. PROCEDURE PutImage(X1,Y1:Integer; VAR P);
  988. VAR
  989.    Data:ARRAY[0..64003] OF Byte ABSOLUTE P;
  990.    Adr,I,XS,YS:Word;
  991.    DataDS,DataSI:Word;
  992. BEGIN
  993.      XS:=Data[0]+Data[1] SHL 8;
  994.      YS:=Data[2]+Data[3] SHL 8;
  995.      Adr:=Word(Y1)*320+X1;
  996.      DataDS:=Seg(Data[4]);
  997.      DataSI:=Ofs(Data[4]);
  998.      ASM
  999.         mov dx,ys
  1000.         inc dx
  1001.         mov bx,xs
  1002.         inc bx
  1003.         mov ax,$a000
  1004.         mov es,ax
  1005.         mov di,adr
  1006.         mov si,DataSI
  1007.         mov ax,DataDS
  1008.         push ds
  1009.         mov ds,ax
  1010.         cld
  1011. @1:     mov cx,bx
  1012.         rep movsb
  1013.         add di,320
  1014.         sub di,bx
  1015.         dec dx
  1016.         jnz @1
  1017.         pop ds
  1018.      END;
  1019. {
  1020.      FOR I:=0 TO YS DO
  1021.          Move(Data[(XS+1)*I+4],Ptr($A000,(Y1+I)*320+X1)^,XS+1);
  1022. }
  1023. END;
  1024.  
  1025. PROCEDURE PutImagePart(X1,Y1,XS2,YS2:Integer; VAR P);
  1026. VAR
  1027.    Data:ARRAY[0..64003] OF Byte ABSOLUTE P;
  1028.    Adr,I,XS,YS:Word;
  1029.    DataDS,DataSI:Word;
  1030. BEGIN
  1031.      XS:=Data[0]+Data[1] SHL 8+1;
  1032.      YS:=Data[2]+Data[3] SHL 8+1;
  1033.      IF (XS2<0) OR (XS2>XS) THEN
  1034.         XS2:=XS;
  1035.      IF (YS2<0) OR (YS2>YS) THEN
  1036.         YS2:=YS;
  1037.      Adr:=Word(Y1)*320+X1;
  1038.      DataDS:=Seg(Data[4]);
  1039.      DataSI:=Ofs(Data[4]);
  1040.      ASM
  1041.         mov dx,ys
  1042.         mov bx,xs2
  1043.         mov ax,$a000
  1044.         mov es,ax
  1045.         mov di,adr
  1046.         mov si,DataSI
  1047.         mov ax,DataDS
  1048.         mov cx,xs
  1049.         sub cx,xs2
  1050.         push ds
  1051.         mov ds,ax
  1052.         mov ax,cx
  1053.         cld
  1054. @1:     mov cx,bx
  1055.         rep movsb
  1056.         add di,320
  1057.         sub di,bx
  1058.         add si,ax
  1059.         dec dx
  1060.         jnz @1
  1061.         pop ds
  1062.      END;
  1063. {
  1064.      FOR I:=0 TO YS DO
  1065.          Move(Data[(XS+1)*I+4],Ptr($A000,(Y1+I)*320+X1)^,XS+1);
  1066. }
  1067. END;
  1068.  
  1069. PROCEDURE FillBlock(X1,Y1,X2,Y2:Integer; C:Byte);
  1070. VAR
  1071.    Y:Integer;
  1072. BEGIN
  1073.      FOR Y:=Y1 TO Y2 DO
  1074.          DrawLineH(X1,X2,Y,C);
  1075. END;
  1076.  
  1077. PROCEDURE ScrollLeft(X1,Y1,X2,Y2:Word);
  1078. BEGIN
  1079.      ASM
  1080.         push ds
  1081.         mov ax,$a000
  1082.         mov es,ax
  1083.         mov ds,ax
  1084.         mov si,[bp+offset y1]
  1085.         mov cx,[bp+offset y2]
  1086.         sub cx,si
  1087.         inc cx
  1088.         mov ax,320
  1089.         mul si
  1090.         mov bx,[bp+offset x1]
  1091.         add ax,bx
  1092.         mov dx,[bp+offset x2]
  1093.         sub dx,bx
  1094.         inc dx
  1095.         cld
  1096. @1:     mov bx,cx
  1097.         mov di,ax
  1098.         dec di
  1099.         mov si,ax
  1100.         mov cx,dx
  1101.         rep movsb
  1102.         mov cx,bx
  1103.         add ax,320
  1104.         loop @1
  1105.         pop ds
  1106.      END;
  1107. END;
  1108.  
  1109. PROCEDURE ScrollRight(X1,Y1,X2,Y2:Word);
  1110. BEGIN
  1111.      ASM
  1112.         push ds
  1113.         mov ax,$a000
  1114.         mov es,ax
  1115.         mov ds,ax
  1116.         mov si,[bp+offset y1]
  1117.         mov cx,[bp+offset y2]
  1118.         sub cx,si
  1119.         inc cx
  1120.         mov ax,320
  1121.         mul si
  1122.         mov bx,[bp+offset x1]
  1123.         mov dx,[bp+offset x2]
  1124.         add ax,dx
  1125.         sub dx,bx
  1126.         inc dx
  1127.         std
  1128. @1:     mov bx,cx
  1129.         mov di,ax
  1130.         mov si,ax
  1131.         dec si
  1132.         mov cx,dx
  1133.         rep movsb
  1134.         mov cx,bx
  1135.         add ax,320
  1136.         loop @1
  1137.         cld
  1138.         pop ds
  1139.      END;
  1140. END;
  1141.  
  1142. PROCEDURE ScrollUp(X1,Y1,X2,Y2:Word);
  1143. BEGIN
  1144.      ASM
  1145.         push ds
  1146.         mov ax,$a000
  1147.         mov es,ax
  1148.         mov ds,ax
  1149.         mov si,[bp+offset y1]
  1150.         mov cx,[bp+offset y2]
  1151.         sub cx,si
  1152.         inc cx
  1153.         mov ax,320
  1154.         mul si
  1155.         mov bx,[bp+offset x1]
  1156.         add ax,bx
  1157.         mov dx,[bp+offset x2]
  1158.         sub dx,bx
  1159.         inc dx
  1160.         cld
  1161. @1:     mov bx,cx
  1162.         mov di,ax
  1163.         sub di,320
  1164.         mov si,ax
  1165.         mov cx,dx
  1166.         rep movsb
  1167.         mov cx,bx
  1168.         add ax,320
  1169.         loop @1
  1170.         pop ds
  1171.      END;
  1172. END;
  1173.  
  1174. PROCEDURE ScrollDown(X1,Y1,X2,Y2:Word);
  1175. BEGIN
  1176.      ASM
  1177.         push ds
  1178.         mov ax,$a000
  1179.         mov es,ax
  1180.         mov ds,ax
  1181.         mov si,[bp+offset y1]
  1182.         mov cx,[bp+offset y2]
  1183.         mov ax,320
  1184.         mul cx
  1185.         sub cx,si
  1186.         inc cx
  1187.         mov bx,[bp+offset x1]
  1188.         mov dx,[bp+offset x2]
  1189.         add ax,bx
  1190.         sub dx,bx
  1191.         inc dx
  1192.         cld
  1193. @1:     mov bx,cx
  1194.         mov di,ax
  1195.         mov si,ax
  1196.         sub si,320
  1197.         mov cx,dx
  1198.         rep movsb
  1199.         mov cx,bx
  1200.         sub ax,320
  1201.         loop @1
  1202.         pop ds
  1203.      END;
  1204. END;
  1205.  
  1206. PROCEDURE Scroll(Direction:Byte; X1,Y1,X2,Y2:Word);
  1207. BEGIN
  1208.      CASE Direction OF
  1209.           Up:ScrollUp(X1,Y1,X2,Y2);
  1210.           Right:ScrollRight(X1,Y1,X2,Y2);
  1211.           Down:ScrollDown(X1,Y1,X2,Y2);
  1212.           Left:ScrollLeft(X1,Y1,X2,Y2);
  1213.      END;
  1214. END;
  1215.  
  1216. PROCEDURE SwitchOff; ASSEMBLER;
  1217. ASM
  1218.    mov dx,$3c4
  1219.    mov al,1
  1220.    out dx,al
  1221.    inc dx
  1222.    in al,dx
  1223.    or al,$20
  1224.    out dx,al
  1225. END;
  1226.  
  1227. PROCEDURE SwitchOn; ASSEMBLER;
  1228. ASM
  1229.    mov dx,$3c4
  1230.    mov al,1
  1231.    out dx,al
  1232.    inc dx
  1233.    in al,dx
  1234.    and al,$df
  1235.    out dx,al
  1236. END;
  1237.  
  1238. PROCEDURE LoadPalette(DateiName:String);
  1239. VAR
  1240.    Datei:File;
  1241.    RGB:ARRAY[0..255,1..3] OF Byte;
  1242.    I:Byte;
  1243. BEGIN
  1244.      Assign(Datei,DateiName+'.PAL');
  1245.      Reset(Datei,1);
  1246.      BlockRead(Datei,RGB,768);
  1247.      SwitchOff;
  1248.      FOR I:=0 TO 255 DO
  1249.          SetColor(I,RGB[I,1],RGB[I,2],RGB[I,3]);
  1250.      SwitchOn;
  1251. END;
  1252.  
  1253. PROCEDURE SavePalette(DateiName:String);
  1254. VAR
  1255.    Datei:File;
  1256.    RGB:ARRAY[0..255,1..3] OF Byte;
  1257.    I:Byte;
  1258. BEGIN
  1259.      Assign(Datei,DateiName+'.PAL');
  1260.      Rewrite(Datei,1);
  1261.      FOR I:=0 TO 255 DO
  1262.          GetColor(I,RGB[I,1],RGB[I,2],RGB[I,3]);
  1263.      BlockWrite(Datei,RGB,768);
  1264. END;
  1265.  
  1266. PROCEDURE LoadScreen(DateiName:String);
  1267. VAR
  1268.    Datei:File;
  1269.    RGB:ARRAY[0..255,1..3] OF Byte;
  1270.    I:Byte;
  1271. BEGIN
  1272.      Assign(Datei,DateiName+'.BLD');
  1273.      Reset(Datei,1);
  1274.      BlockRead(Datei,RGB,768);
  1275.      SwitchOff;
  1276.      FOR I:=0 TO 255 DO
  1277.          SetColor(I,RGB[I,1],RGB[I,2],RGB[I,3]);
  1278.      BlockRead(Datei,Ptr($A000,0)^,64000);
  1279.      SwitchOn;
  1280.      Close(Datei);
  1281. END;
  1282.  
  1283. PROCEDURE SaveScreen(DateiName:String);
  1284. VAR
  1285.    Datei:File;
  1286.    RGB:ARRAY[0..255,1..3] OF Byte;
  1287.    I:Byte;
  1288. BEGIN
  1289.      Assign(Datei,DateiName+'.BLD');
  1290.      Rewrite(Datei,1);
  1291.      FOR I:=0 TO 255 DO
  1292.          GetColor(I,RGB[I,1],RGB[I,2],RGB[I,3]);
  1293.      BlockWrite(Datei,RGB,768);
  1294.      BlockWrite(Datei,Ptr($A000,0)^,64000);
  1295.      Close(Datei);
  1296. END;
  1297.  
  1298. PROCEDURE BCircle(X,Y,R:Integer; C:Byte);
  1299. VAR
  1300.    XX4,XX,YY,D:Integer;
  1301. BEGIN
  1302.      XX:=0;
  1303.      YY:=R;
  1304.      D:=3-(2*R);
  1305.      WHILE XX<=YY DO
  1306.      BEGIN
  1307.           SetPixel(X+XX,Y+YY,C);
  1308.           SetPixel(X-XX,Y+YY,C);
  1309.           SetPixel(X+XX,Y-YY,C);
  1310.           SetPixel(X-XX,Y-YY,C);
  1311.           SetPixel(X+YY,Y+XX,C);
  1312.           SetPixel(X-YY,Y+XX,C);
  1313.           SetPixel(X+YY,Y-XX,C);
  1314.           SetPixel(X-YY,Y-XX,C);
  1315.           XX4:=XX SHL 2;
  1316.           IF D<0 THEN
  1317.              Inc(D,XX4+6)
  1318.           ELSE
  1319.           BEGIN
  1320.                Inc(D,XX4-YY SHL 2+10);
  1321.                Dec(YY);
  1322.           END;
  1323.           Inc(XX);
  1324.      END;
  1325. END;
  1326.  
  1327. PROCEDURE BFillCircle(X,Y,R:Integer; C:Byte);
  1328. VAR
  1329.    XX4,XX,YY,D:Integer;
  1330. BEGIN
  1331.      XX:=0;
  1332.      YY:=R;
  1333.      D:=3-(2*R);
  1334.      WHILE XX<=YY DO
  1335.      BEGIN
  1336.           DrawLineH(X-XX,X+XX,Y+YY,C);
  1337.           DrawLineH(X-XX,X+XX,Y-YY,C);
  1338.           DrawLineH(X-YY,X+YY,Y+XX,C);
  1339.           DrawLineH(X-YY,X+YY,Y-XX,C);
  1340.           XX4:=XX SHL 2;
  1341.           IF D<0 THEN
  1342.              Inc(D,XX4+6)
  1343.           ELSE
  1344.           BEGIN
  1345.                Inc(D,XX4-YY SHL 2+10);
  1346.                Dec(YY);
  1347.           END;
  1348.           Inc(XX);
  1349.      END;
  1350. END;
  1351.  
  1352. PROCEDURE Split(Row:Integer);
  1353. BEGIN
  1354.      ASM
  1355.         mov dx,$3d4
  1356.         mov ax,row
  1357.         mov bh,ah
  1358.         mov bl,ah
  1359.         and bx,201h
  1360.         mov cl,4
  1361.         shl bx,cl
  1362.         mov ah,al
  1363.         mov al,18h
  1364.         out dx,ax
  1365.         mov al,7
  1366.         cli
  1367.         out dx,al
  1368.         inc dx
  1369.         in al,dx
  1370.         sti
  1371.         dec dx
  1372.         mov ah,al
  1373.         and ah,0efh
  1374.         or ah,bl
  1375.         mov al,7
  1376.         out dx,ax
  1377.         mov al,9
  1378.         cli
  1379.         out dx,al
  1380.         inc dx
  1381.         in al,dx
  1382.         sti
  1383.         dec dx
  1384.         mov ah,al
  1385.         and ah,0bfh
  1386.         shl bh,1
  1387.         shl bh,1
  1388.         or ah,bh
  1389.         mov al,9
  1390.         out dx,ax
  1391.      END;
  1392. END;
  1393.  
  1394. PROCEDURE ScrollText(Nr:Word);
  1395. BEGIN
  1396.      ASM
  1397.         mov ax,nr
  1398.         push es
  1399.         push cx
  1400.         push dx
  1401.         mov cx,$40
  1402.         mov es,cx
  1403.         mov cl,es:[$85]
  1404.         div cl
  1405.         mov cx,ax
  1406.         mov dx,es:[$63]
  1407.         push dx
  1408.         mov al,$13
  1409.         cli
  1410.         out dx,al
  1411.         jmp @1
  1412. @1:     inc dx
  1413.         in al,dx
  1414.         sti
  1415.         mul cl
  1416.         shl ax,1
  1417.         mov es:[$4e],ax
  1418.         pop dx
  1419.         mov cl,al
  1420.         mov al,$c
  1421.         out dx,ax
  1422.         jmp @2
  1423. @2:     mov al,$d
  1424.         mov ah,cl
  1425.         out dx,ax
  1426.         jmp @3
  1427. @3:     mov ah,ch
  1428.         mov al,8
  1429.         out dx,ax
  1430.         pop dx
  1431.         pop cx
  1432.         pop es
  1433.      END;
  1434. END;
  1435.  
  1436. PROCEDURE SetStart(S:Word);
  1437. BEGIN
  1438.      ASM
  1439.         mov bx,s
  1440.         mov dx,$3d4
  1441.         mov al,$c
  1442.         mov ah,bh
  1443.         out dx,ax
  1444.         inc ax
  1445.         mov ah,bl
  1446.         out dx,ax
  1447.      END;
  1448. END;
  1449.  
  1450. PROCEDURE VerticalRetrace;
  1451. BEGIN
  1452.      ASM
  1453.         mov dx,$3da
  1454. @1:     in al,dx
  1455.         test al,8
  1456.         jz @1
  1457. @2:     in al,dx
  1458.         test al,8
  1459.         jnz @2
  1460.      END;
  1461. END;
  1462.  
  1463. PROCEDURE SetOffset(B:Byte);
  1464. BEGIN
  1465.      ASM
  1466.         mov dx,$3d4
  1467.         mov al,$13
  1468.         mov ah,b
  1469.         out dx,ax
  1470.      END;
  1471. END;
  1472.  
  1473. PROCEDURE LoadSprite(DateiName:String; VAR P);
  1474. VAR
  1475.    Datei:File;
  1476.    Size,I:Word;
  1477.    P2:Pointer ABSOLUTE P;
  1478. BEGIN
  1479.      Assign(Datei,DateiName+'.SPR');
  1480.      Reset(Datei,1);
  1481.      Size:=FileSize(Datei);
  1482.      GetMem(P2,Size+15);
  1483.      IF Ofs(P2^)<>0 THEN
  1484.         P2:=Ptr(Seg(P2^)+1,0);
  1485.      BlockRead(Datei,P2^,Size);
  1486.      Close(Datei);
  1487. END;
  1488.  
  1489. PROCEDURE SaveSprite(DateiName:String; VAR P);
  1490. VAR
  1491.    A:ARRAY[-4..32000] OF Byte ABSOLUTE P;
  1492.    Datei:File;
  1493.    Size,I:Word;
  1494.    XS,YS:Word;
  1495. BEGIN
  1496.      XS:=A[-4]+A[-3] SHL 8;
  1497.      YS:=A[-2]+A[-1] SHL 8;
  1498.      Assign(Datei,DateiName+'.SPR');
  1499.      Rewrite(Datei,1);
  1500.      Size:=(XS+1)*(YS+1)+4;
  1501.      BlockWrite(Datei,A,Size);
  1502.      Close(Datei);
  1503. END;
  1504.  
  1505. PROCEDURE FillScreen(C:Byte);
  1506. BEGIN
  1507.      ASM
  1508.         mov ax,$a000
  1509.         mov es,ax
  1510.         mov al,c
  1511.         mov ah,al
  1512.         cld
  1513.         xor di,di
  1514.         mov cx,32000
  1515.         rep stosw
  1516.      END;
  1517. END;
  1518.  
  1519. PROCEDURE Unchain;
  1520. BEGIN
  1521.      PortW[$3C4]:=$0604;
  1522.      PortW[$3C4]:=$0100;
  1523.      Port[$3C2]:=$E7;
  1524.      PortW[$3C4]:=$0300;
  1525.      PortW[$3D4]:=$0014;
  1526.      PortW[$3D4]:=$E317;
  1527.      PortW[$3C4]:=$0F02;
  1528. END;
  1529.  
  1530. PROCEDURE Rechain;
  1531. BEGIN
  1532.      PortW[$3C4]:=$0E04;
  1533.      PortW[$3C4]:=$0100;
  1534.      Port[$3C2]:=$E7;
  1535.      PortW[$3C4]:=$0300;
  1536.      PortW[$3D4]:=$4014;
  1537.      PortW[$3D4]:=$A317;
  1538. END;
  1539.  
  1540. PROCEDURE ClearScreen;
  1541. BEGIN
  1542.      PortW[$3C4]:=$0F02;
  1543.      ASM
  1544.         mov ax,$a000
  1545.         mov es,ax
  1546.         mov cx,16383
  1547.         db $66
  1548.         xor ax,ax
  1549.         xor di,di
  1550.         cld
  1551.         db $66
  1552.         rep stosw
  1553.      END;
  1554. END;
  1555.  
  1556. PROCEDURE SetChain4;
  1557. BEGIN
  1558.      Port[$3CE]:=$05;
  1559.      Port[$3CF]:=Port[$3CF] AND $EF;
  1560.      Port[$3CE]:=$06;
  1561.      Port[$3CF]:=Port[$3CF] AND $FD;
  1562.      Port[$3C4]:=$04;
  1563.      Port[$3C5]:=Port[$3C5] AND $F7;
  1564.      Port[$3D4]:=$14;
  1565.      Port[$3D5]:=Port[$3D5] AND $BF;
  1566.      Port[$3D4]:=$17;
  1567.      Port[$3D5]:=Port[$3D5] OR $40;
  1568. END;
  1569.  
  1570. PROCEDURE ClearChain4;
  1571. BEGIN
  1572.      ASM
  1573.         mov ax,$a000
  1574.         mov es,ax
  1575.         mov cx,32768
  1576.         xor di,di
  1577.         cld
  1578.         xor ax,ax
  1579.         rep stosw
  1580.      END;
  1581. END;
  1582.  
  1583. PROCEDURE CharHeight(B:Byte);
  1584. BEGIN
  1585.      Port[$3D4]:=$09;
  1586.      Port[$3D5]:=(Port[$3D5] AND $E0) OR B;
  1587. END;
  1588.  
  1589. PROCEDURE Wait4Line;
  1590. BEGIN
  1591.      ASM
  1592.         mov dx,$3da
  1593. @1:     in al,dx
  1594.         test al,1
  1595.         jnz @1
  1596. @2:     in al,dx
  1597.         test al,1
  1598.         jz @2
  1599.      END;
  1600. END;
  1601.  
  1602. PROCEDURE CLI; ASSEMBLER;
  1603. ASM
  1604.    cli
  1605. END;
  1606.  
  1607. PROCEDURE STI; ASSEMBLER;
  1608. ASM
  1609.    sti
  1610. END;
  1611.  
  1612. PROCEDURE SetWriteMap(Map:Byte);
  1613. BEGIN
  1614.      Port[$3C4]:=2;
  1615.      Port[$3C5]:=Map;
  1616. END;
  1617.  
  1618. PROCEDURE PutImage4(X1,Y1:Integer; VAR P);
  1619. VAR
  1620.    Data:ARRAY[0..64003] OF Byte ABSOLUTE P;
  1621.    Adr,I,J,K,XS,YS:Word;
  1622.    DataDS,DataSI:Word;
  1623. BEGIN
  1624.      XS:=Data[0]+Data[1] SHL 8;
  1625.      YS:=Data[2]+Data[3] SHL 8;
  1626.      DataDS:=Seg(Data);
  1627.      FOR J:=0 TO YS DO
  1628.      BEGIN
  1629.           DataSI:=Ofs(Data)+4+(XS+1)*J;
  1630.           FOR K:=0 TO 3 DO
  1631.           BEGIN
  1632.                Adr:=Word(Y1+J)*80+(X1+K) SHR 2;
  1633.                SetWriteMap(1 SHL ((X1+K) AND 3));
  1634.                ASM
  1635.                   push ds
  1636.                   mov ax,$a000
  1637.                   mov es,ax
  1638.                   mov di,adr
  1639.                   mov cx,xs
  1640.                   shr cx,2
  1641.                   inc cx
  1642.                   mov si,datasi
  1643.                   mov ax,datads
  1644.                   mov ds,ax
  1645.                   mov bx,3
  1646.                   cld
  1647. @1:               movsb
  1648.                   add si,bx
  1649.                   loop @1
  1650.                   pop ds
  1651.                END;
  1652.                Inc(DataSI);
  1653.           END;
  1654.      END;
  1655. END;
  1656.  
  1657. FUNCTION SpriteXSize(Sprite:Pointer):Word;
  1658. BEGIN
  1659.      ASM
  1660.         push ds
  1661.         lds si,sprite
  1662.         lodsw
  1663.         inc ax
  1664.         mov @result,ax
  1665.         pop ds
  1666.      END;
  1667. END;
  1668.  
  1669. FUNCTION SpriteYSize(Sprite:Pointer):Word;
  1670. BEGIN
  1671.      ASM
  1672.         push ds
  1673.         lds si,sprite
  1674.         lodsw
  1675.         lodsw
  1676.         inc ax
  1677.         mov @result,ax
  1678.         pop ds
  1679.      END;
  1680. END;
  1681.  
  1682. FUNCTION SpriteSize(Sprite:Pointer):Word;
  1683. BEGIN
  1684.      ASM
  1685.         push ds
  1686.         lds si,sprite
  1687.         lodsw
  1688.         inc ax
  1689.         mov bx,ax
  1690.         lodsw
  1691.         inc ax
  1692.         mul bx
  1693.         add ax,4
  1694.         mov @result,ax
  1695.         pop ds
  1696.      END;
  1697. END;
  1698.  
  1699. PROCEDURE SetWriteMode(M:Byte);
  1700. BEGIN
  1701.      Port[$3CE]:=$05;
  1702.      Port[$3CF]:=(Port[$3CF] AND $FC) OR (M AND 3);
  1703. END;
  1704.  
  1705. PROCEDURE SetModeNr(Nr:Word);
  1706.  
  1707. BEGIN
  1708.      ASM
  1709.         mov ax,nr
  1710.         int $10
  1711.      END;
  1712. END;
  1713.  
  1714. PROCEDURE SetReg(Reg:Word; Index,Value:Byte);
  1715. VAR
  1716.    B:Byte;
  1717. BEGIN
  1718.      CASE Reg OF
  1719.           $3C0:BEGIN
  1720.                     B:=Port[$3DA];
  1721.                     Port[$3C0]:=Index OR $20;
  1722.                     Port[$3C0]:=Value;
  1723.                END;
  1724.           $3C2,$3C3:Port[Reg]:=Value;
  1725.           ELSE
  1726.           BEGIN
  1727.                Port[Reg]:=Index;
  1728.                Port[Reg+1]:=Value;
  1729.           END;
  1730.      END;
  1731. END;
  1732.  
  1733. PROCEDURE SetModeReg(Reg:String);
  1734. TYPE
  1735.     RegRec=RECORD
  1736.                  Reg:Word;
  1737.                  Index:Byte;
  1738.                  Value:Byte;
  1739.            END;
  1740. VAR
  1741.    RegFile:File OF RegRec;
  1742.    RegSet:RegRec;
  1743. BEGIN
  1744.      Port[$3D4]:=$11;
  1745.      Port[$3D5]:=Port[$3D5] AND $7F;
  1746.      Assign(RegFile,Reg+'.REG');
  1747.      Reset(RegFile);
  1748.      WHILE NOT Eof(RegFile) DO
  1749.      BEGIN
  1750.           Read(RegFile,RegSet);
  1751.           WITH RegSet DO
  1752.                SetReg(Reg,Index,Value);
  1753.      END;
  1754.      ClearScreen;
  1755. END;
  1756.  
  1757. PROCEDURE Init13X;
  1758. BEGIN
  1759.      MCGAOn;
  1760.      SwitchOff;
  1761.      Unchain;
  1762.      ClearScreen;
  1763.      SwitchOn;
  1764. END;
  1765.  
  1766. PROCEDURE SetReadMap(Map:Byte);
  1767. BEGIN
  1768.      PortW[$3CE]:=Map SHL 8+4;
  1769. END;
  1770.  
  1771. PROCEDURE SetLineRepeat(Nr:Byte);
  1772. BEGIN
  1773.      Port[$3D4]:=9;
  1774.      Port[$3D5]:=Port[$3D5] AND $F0+Nr;
  1775. END;
  1776.  
  1777. PROCEDURE SetDoubleLines(Ok:Boolean);
  1778. BEGIN
  1779.      Port[$3D4]:=9;
  1780.      Port[$3D5]:=Port[$3D5] AND $7F+Ord(Ok) SHL 7;
  1781. END;
  1782.  
  1783. PROCEDURE SetHorizOfs(Count:Byte);
  1784. VAR
  1785.    I:Byte;
  1786. BEGIN
  1787.      I:=Port[$3DA];
  1788.      Port[$3C0]:=$33;
  1789.      Port[$3C0]:=Count SHL 1;
  1790. END;
  1791.  
  1792. PROCEDURE DrawLineH4(X1,X2,Y:Integer; C:Byte);
  1793. BEGIN
  1794.      ASM
  1795.         mov ax,0a000h
  1796.         mov es,ax
  1797.         mov ax,y
  1798.         mov di,ax
  1799.         shl ax,2
  1800.         add di,ax
  1801.         shl di,4
  1802.         mov ax,x1
  1803.         shr ax,2
  1804.         add di,ax
  1805.         mov ax,x1
  1806.         mov bx,x2
  1807.         cmp ax,bx
  1808.         jg @2
  1809.         shr ax,2
  1810.         shr bx,2
  1811.         cld
  1812.         mov dx,$3c4
  1813.         cmp ax,bx
  1814.         jnz @1
  1815.         mov al,2
  1816.         mov cx,x1
  1817.         and cl,3
  1818.         mov ah,$e0
  1819.         rol ah,cl
  1820.         mov cx,x2
  1821.         and cl,3
  1822.         inc cx
  1823.         mov bh,15
  1824.         shl bh,cl
  1825.         or ah,bh
  1826.         xor ah,$0f
  1827.         out dx,ax
  1828.         mov al,c
  1829.         stosb
  1830.         jmp @2
  1831. @1:     mov al,2
  1832.         mov cx,x1
  1833.         and cl,3
  1834.         mov ah,$1F
  1835.         rol ah,cl
  1836.         out dx,ax
  1837.         mov al,c
  1838.         stosb
  1839.         mov al,2
  1840.         mov ah,$F
  1841.         out dx,ax
  1842.         mov ax,x1
  1843.         mov bx,x2
  1844.         inc bx
  1845.         shr ax,2
  1846.         shr bx,2
  1847.         dec bx
  1848.         sub bx,ax
  1849.         mov cx,bx
  1850.         mov al,c
  1851.         mov ah,al
  1852.         shr cx,1
  1853.         jnc @3
  1854.         stosb
  1855. @3:     rep stosw
  1856.         mov cx,x2
  1857.         inc cx
  1858.         and cl,3
  1859.         mov ah,$F0
  1860.         rol ah,cl
  1861.         mov al,2
  1862.         out dx,ax
  1863.         mov al,c
  1864.         stosb
  1865. @2:  END;
  1866. END;
  1867.  
  1868. PROCEDURE DrawLineV4(X,Y1,Y2:Integer; C:Byte);
  1869. BEGIN
  1870.      SetWriteMap(1 SHL (X AND 3));
  1871.      ASM
  1872.         mov ax,0a000h
  1873.         mov es,ax
  1874.         mov ax,y1
  1875.         mov cx,y2
  1876.         sub cx,ax
  1877.         inc cx
  1878.         shl ax,4
  1879.         mov di,ax
  1880.         shl ax,2
  1881.         add di,ax
  1882.         mov ax,x
  1883.         shr ax,2
  1884.         add di,ax
  1885.         mov al,c
  1886.         cld
  1887. @1:     stosb
  1888.         add di,79
  1889.         loop @1
  1890.      END;
  1891. END;
  1892.  
  1893. BEGIN
  1894. END.
  1895.